//package com.dx.security.provider;
//
//import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.security.authentication.InternalAuthenticationServiceException;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.core.userdetails.UserDetails;
//import org.springframework.security.core.userdetails.UserDetailsPasswordService;
//import org.springframework.security.core.userdetails.UserDetailsService;
//import org.springframework.security.core.userdetails.UsernameNotFoundException;
//import org.springframework.security.crypto.factory.PasswordEncoderFactories;
//import org.springframework.security.crypto.password.PasswordEncoder;
//import org.springframework.util.Assert;
//
///**
// * @author : Yu.Tan
// * @date : 2023/7/23 17:18
// * @desc : this class for 做SaaS平台，多渠道登录，名称允许重复的话
// *
// * 自定义一个DaoAuthenticationProvider
// * 新建CustomerDaoAuthenticationProvider.java，其实是把DaoAuthenticationProvider代码抄下来，
// * 修改了userDetailsService和UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username, authentication.getDetails());。
// * 把UsernamePasswordAuthenticationToken的details属性作为扩展参数传入新的loadUserByUsername方法。
// **/
//public class CustomerDaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
//    private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
//    private PasswordEncoder passwordEncoder;
//    private volatile String userNotFoundEncodedPassword;
//    private UserDetailsService userDetailsService;
//    private UserDetailsPasswordService userDetailsPasswordService;
//
//    public CustomerDaoAuthenticationProvider() {
//        this.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
//    }
//
//    @Override
//    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//        if (authentication.getCredentials() == null) {
//            this.logger.debug("Authentication failed: no credentials provided");
//            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
//        } else {
//            String presentedPassword = authentication.getCredentials().toString();
//            if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
//                this.logger.debug("Authentication failed: password does not match stored value");
//                throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
//            }
//        }
//    }
//
//    @Override
//    protected void doAfterPropertiesSet() throws Exception {
//        Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
//    }
//
//    @Override
//    protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
//        this.prepareTimingAttackProtection();
//
//        try {
//            UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username,authentication.getDetails());
//            if (loadedUser == null) {
//                throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
//            } else {
//                return loadedUser;
//            }
//        } catch (UsernameNotFoundException var4) {
//            this.mitigateAgainstTimingAttack(authentication);
//            throw var4;
//        } catch (InternalAuthenticationServiceException var5) {
//            throw var5;
//        } catch (Exception var6) {
//            throw new InternalAuthenticationServiceException(var6.getMessage(), var6);
//        }
//    }
//
//    @Override
//    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
//        boolean upgradeEncoding = this.userDetailsPasswordService != null && this.passwordEncoder.upgradeEncoding(user.getPassword());
//        if (upgradeEncoding) {
//            String presentedPassword = authentication.getCredentials().toString();
//            String newPassword = this.passwordEncoder.encode(presentedPassword);
//            user = this.userDetailsPasswordService.updatePassword(user, newPassword);
//        }
//
//        return super.createSuccessAuthentication(principal, authentication, user);
//    }
//
//    private void prepareTimingAttackProtection() {
//        if (this.userNotFoundEncodedPassword == null) {
//            this.userNotFoundEncodedPassword = this.passwordEncoder.encode("userNotFoundPassword");
//        }
//
//    }
//
//    private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
//        if (authentication.getCredentials() != null) {
//            String presentedPassword = authentication.getCredentials().toString();
//            this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword);
//        }
//
//    }
//
//    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
//        Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
//        this.passwordEncoder = passwordEncoder;
//        this.userNotFoundEncodedPassword = null;
//    }
//
//    protected PasswordEncoder getPasswordEncoder() {
//        return this.passwordEncoder;
//    }
//
//    public void setUserDetailsService(UserDetailsService userDetailsService) {
//        this.userDetailsService = userDetailsService;
//    }
//
//    protected UserDetailsService getUserDetailsService() {
//        return this.userDetailsService;
//    }
//
//    public void setUserDetailsPasswordService(UserDetailsPasswordService userDetailsPasswordService) {
//        this.userDetailsPasswordService = userDetailsPasswordService;
//    }
//}
